package com.antdant.utils;

import com.antdant.constant.UserConstant;
import com.antdant.exception.GeneralException;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author Lee Yunc
 * @Date 2021/2/23 15:51
 * @Description: 生成token令牌的工具类
 * @Version 1.0
 */
public class UserTokenUtils {

    //密钥
    private static final String SECRET = "TBJsQAOKsANsDNUdDUfXNBWhSYLbTLAXkAROhEXTSrtUkTTKnDXUFpEBOxMWWmTYlCF";

    public static synchronized String generateUserToken(String loginId) throws UnsupportedEncodingException {
        /**
         * token header
         * Header 部分是一个 JSON 对象，描述 JWT 的元数据，通常是下面的样子。
         * {
         *   "alg": "HS256",
         *   "typ": "JWT"
         * }
         */
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");

        //签名
        Algorithm algorithm = Algorithm.HMAC256(SECRET);
        String token = JWT.create()
                .withHeader(map)
                .withClaim("loginId", loginId)
                .withSubject("auth0")
                .withIssuer("auth0")
                .withIssuedAt(new Date())
                .sign(algorithm);
        return token;
    }

    public static String generateUserTokenCacheKey(String userToken) {
        return String.format("%s%s", UserConstant.USER_TOKEN_CACHE_KEY_PREFIX, userToken);
    }

    /**
     * 解析token
     *
     * @param token
     * @return
     * @throws Exception
     */
    public static synchronized Map<String, Claim> parseToken(String token) throws Exception {
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        DecodedJWT jwt = null;
        try {
            jwt = verifier.verify(token);
            return jwt.getClaims();
        } catch (Exception e) {
            throw new GeneralException("token解析异常");
        }
    }

    /**
     * 验证loginId是否匹配token
     *
     * @param loginId
     * @param token
     * @return
     * @throws Exception
     */
    public boolean verifyLoginIdByToken(String loginId, String token) throws Exception {
        if (DataUtils.isEmptyStr(loginId) || DataUtils.isEmptyStr(token)) {
            return false;
        }
        if (loginId.equals(parseToken(token).get("loginId").asString())) {
            return true;
        }
        return false;
    }
}
